package com.jxpanda.infrastructure.crypto.algorithm.encrypt.contract;

import com.jxpanda.infrastructure.crypto.algorithm.Crypto;
import com.jxpanda.infrastructure.crypto.model.BinaryData;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;

public interface Encrypt<K> extends Crypto {

    K getKey();

    default BinaryData encrypt(byte[] contentBytes) {
        return encrypt(new BinaryData(contentBytes));
    }

    default BinaryData encrypt(String contentText) {
        return encrypt(BinaryData.fromString(contentText));
    }

    default BinaryData encryptFromBase64(String base64Text) {
        return encrypt(BinaryData.fromBase64(base64Text));
    }

    default BinaryData encrypt(BinaryData binaryData) {
        try {
            return new BinaryData(getEncoder().doFinal(binaryData.bytes()));
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }

    default BinaryData decrypt(byte[] contentBytes) {
        return decrypt(new BinaryData(contentBytes));
    }

    default BinaryData decrypt(String contentText) {
        return decrypt(BinaryData.fromString(contentText));
    }

    default BinaryData decryptFromBase64(String base64Text) {
        return decrypt(BinaryData.fromBase64(base64Text));
    }

    default BinaryData decrypt(BinaryData binaryData) {
        try {
            return new BinaryData(getDecoder().doFinal(binaryData.bytes()));
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }

    default Cipher getEncoder() {
        return createCipher(Cipher.ENCRYPT_MODE);
    }

    default Cipher getDecoder() {
        return createCipher(Cipher.DECRYPT_MODE);
    }

    Cipher createCipher(int mode);

}
